// PluginICPopenCVApp.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"

#include <iostream>

#include "resource.h"

#include "..\..\PublicInterfaces\PluginICPopenCV\OCV-Dev-ProductID.h"
#include "MxUtils\MxError1.h"
#include "MxUtils\MxUtils1.h"

#include "MxPluginManager\MxPluginManager1.h"
#include "MxPluginManager\MxPluginLib1.h"

#include "PublicInterfaces\{FAFD3CB8-FCF3-46EE-B32E-45A4FF68073E}\IImageComputePluginLib.h"
#include "PublicInterfaces\{FAFD3CB8-FCF3-46EE-B32E-45A4FF68073E}\IImageCompute.h"

#include "..\..\PublicInterfaces\PluginICPopenCV\IPluginICPopenCV.h"
#include "..\..\PublicInterfaces\PluginICPopenCV\PluginICPopenCVErrorCodes.h"

#include "PluginICPopenCVAppErrorCodes.h"


int  DisplayError(int errorCode);

int main(int argc, char* argv[])		//argv[1] is IPS Output pathfilename
{
	int rc = -1;

	MxVersionInfo app;
	MX_SETUP (app.GetOwner(), PRODID_PluginICPopenCVApp, app.GetProductName(), app.GetVersion(), MxError::Development, MxError::VerboseReport, "app starts");  

	std::cout << app.GetProductName() << " v" << app.GetVersion() << std::endl << std::endl;

	if ((argc < 2) || (argv == nullptr))
		MX_SETERROR( MX11701, MxError::BadUserInput, MxError::Abort,  MxError::QuietReport, "invalid argc=%d missing IFS id, or argv is null", argc);
	else
	{	
		std::string Outputfile  = argv[1];
		try
		{
			MxPluginManager pluginMngr;
			if (pluginMngr.RefreshPluginsInRootFolder(SID_ImageProc, true) == false)
				MX_SETERROR(MX11702, MxError::System,  MxError::Abort,  MxError::VerboseReport, "RefreshPluginsInRootFolder(PRODID_DefaultPluginRootFolder, SID_ImageCompute) failed"); 
			else
			{
				MxPluginLib *plugin = nullptr;
				if ((plugin = pluginMngr.GetPlugin(PRODID_PluginICPopenCV)) == nullptr)
					MX_SETERROR(MX11703, MxError::System,  MxError::Abort,  MxError::VerboseReport, "unable to find PluginImageCompute"); 
				else
				{
					IMxPluginLibDetails *iPluginDetails = nullptr;
					if ((iPluginDetails = plugin->GetIMxPluginLibDetails()) == nullptr)
						MX_SETERROR( MX11704, MxError::CodeDefect,  MxError::Abort,  MxError::VerboseReport, "unable to obtain IMxPluginLibDetails"); 
					else
					{
						std::cout << "loaded " << iPluginDetails->GetLibName() << " v" << iPluginDetails->GetLibVersion() << ", " << iPluginDetails->GetLibDescription() << std::endl;

						IImageComputePluginLib* iImageComputeLib = nullptr;
						if (((iImageComputeLib = static_cast<IImageComputePluginLib *>(plugin->CreateClassInstance(IImageComputePluginLibIID::Guid())))) == nullptr)
							MX_SETERROR( MX11705, MxError::System,  MxError::Abort,  MxError::VerboseReport, "unable to obtain IImageComputePluginLib"); 
						else
						{
							IImageCompute *iImageCompute = nullptr;
							if ((iImageCompute = iImageComputeLib->GetIImageCompute()) == nullptr)
								MX_SETERROR( MX11706, MxError::CodeDefect,  MxError::Abort,  MxError::QuietReport, "unable to obtain IImageCompute"); 
							else
							{
								std::cout << iImageComputeLib->GetToolboxLabel() << " function(s) found=" << iImageCompute->GetFunctionCount() << std::endl << std::endl;

								std::string result("");
								IImageComputeFnDef *iImageComputeFnDef = nullptr;
								GUID FnId = GUID_Invalid;
								for (int x = 0; x < iImageCompute->GetFunctionCount(); x++)
								{
									if (MxGUID::IsValid(FnId = iImageCompute->GetFunctionID(x)) == false)
									{
										MX_SETERROR( MX11707, MxError::CodeDefect,  MxError::Abort,  MxError::VerboseReport, "iImageCompute->GetFunctionID(%d) is invalid", x); 
										break;
									}
									if((iImageComputeFnDef = iImageCompute->GetIImageComputeFnDef(FnId)) == nullptr)
									{
										MX_SETERROR( MX11708, MxError::CodeDefect,  MxError::Abort,  MxError::VerboseReport, "iImageCompute->GetImageComputeFnDef(%s) is null", MxGUID::ConvertToString(FnId, &result)); 
										break;
									}
									else
									{
										std::cout << iImageComputeFnDef->GetLabel() << ", " << iImageComputeFnDef->GetDescription() << std::endl;
										iImageComputeFnDef->DestroyPtr();
									}
								}
								std::cout << std::endl;

								if (iImageCompute->SaveImagePluginSpec(Outputfile.c_str()) == false)
									MX_SETERROR( MX11709, MxError::System,  MxError::Abort,  MxError::VerboseReport, "failed iImageCompute->SaveImagePluginSpec(%s)", Outputfile.c_str()); 
								else
								{
									std::cout << "SUCCESS: IPS written to " << Outputfile << std::endl << std::endl;
								}
								iImageCompute->DestroyPtr();
							}
							iImageComputeLib->DestroyPtr();
						}
						iPluginDetails->DestroyPtr();
					}
				}
			}
		}
		catch(std::exception const& e)
		{
			MX_SETERROR(MX11710, MxError::CodeDefect,  MxError::Abort,  MxError::QuietReport, "Unexpected exception: %s", e.what()); 
		}
	}

	if (MxError::Inst().IsErrorSet())
		rc = DisplayError(MxError::Inst().GetLastErrorCode());
	else
		rc = 0;

	std::cout << app.GetProductName() << " ends" << std::endl;
	MX_END(MxError::VerboseReport, "ends");
	return rc;

}


int DisplayError(int errorCode)
{
	wchar_t buff[1024];
	std::string errMsg(MxError::Inst().GetLastErrorStr());
	std::string errType(MxError::Inst().GetErrorCategoryStr( MxError::Inst().GetErrorCategory()));
	errType += ": ";

	HINSTANCE hInst = NULL;
	//if (IS_ERROR_RANGE_PLUGINICPOPENCV(errorCode) == true)
	//	hInst = VerInfo::Inst().GethModule();
	if (LoadString(hInst, errorCode, buff, 1024) == 0)
		std::cout << "ERROR (" << MxError::Inst().GetErrorCode() << ") " << errType << errMsg << std::endl;
	else
		std::cout << "ERROR (" << MxError::Inst().GetErrorCode() << ") " << errType << MxUtils::ConvertWString2String(&errMsg, buff) << std::endl;

	MxError::Inst().Reset();

	return errorCode;
}

